﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Diagnostics;
using StockFinder.HistoricalPriceAnalysers;
using StockFinder.Indicators.Day.ClosePrice;
using StockFinder.Indicators.Day.Volume;
using StockFinder.Model;
using StockFinder.Model.Constants;
using log4net;
using StockFinder.IBD;
using StockFinder.NorgatePremiumData;
using System.Text;
using System.Net.Mail;
using System.Net;

namespace StockFinder.Consoles.PriceAnalyser
{
    /// <summary>
    /// Loops stocks, and runs certain price analysers against historical prices
    /// </summary>
    class Program
    {
        private static readonly ILog _Log = LogManager.GetLogger(typeof(Program));          

        static void Main(string[] args)
        {
            #region Local variables
            var premiumDataStockFilePathsExtractor = new NorgatePremiumDataStockFilePathsExtractor();
            var allTimeHighBreakoutPriceDatabaseAnalyser = new AllTimeHighBreakoutPriceDatabaseAnalyser();
            var atr14Indicator = new ExponentialMovingAverageTrueRangeClosePriceDayIndicator(14, DayIndicatorNames.CLOSE_EMATR14);
            var sma50Daily = new SimpleMovingAverageClosePriceDayIndicator(50, DayIndicatorNames.CLOSE_SMA50);            
            #endregion

            /* GET IBD RATINGS */

            _Log.DebugFormat("Running IBDRatingDatabaseUpdater...");

            var ibdRatingDatabaseUpdater = new IBDRatingDatabaseUpdater();
            _Log.DebugFormat("Loading IBD Ratings from file");
            ibdRatingDatabaseUpdater.LoadFromFile();            

            /* GET LIST OF STOCK PRICE HISTORY FILENAMES */

            List<string> stockFilenames = premiumDataStockFilePathsExtractor.GetStockPriceHistoryFilenames();

            _Log.DebugFormat("Found {0} stock file paths", stockFilenames.Count);

            /* LOOP STOCK PRICE HISTORY FILENAMES AND RUN ANALYSERS */

            #region Temp variables
            int stocksFilenamesCount = stockFilenames.Count;
            List<DailyPrice> historicPrices = null;
            HistoricPriceAnalyserResult allTimeHighResult = null;
            var successfulResults = new List<HistoricPriceAnalyserResult>();
            string stockFilePath = null;
            FileInfo fileInfo = null;
            Stopwatch stopwatch = new Stopwatch();
            #endregion
            
            stopwatch.Start();

            for (int i = 0; i < stocksFilenamesCount; i++)
            {
                stockFilePath = stockFilenames[i];
                fileInfo = new FileInfo(stockFilePath);

                _Log.DebugFormat("Loading prices for {0}", stockFilePath);

                historicPrices = premiumDataStockFilePathsExtractor.GetStockPriceHistoryFromFilename(stockFilePath);                

                _Log.DebugFormat("Loaded {0} prices", historicPrices.Count);

                //run indicators
                atr14Indicator.ApplyIndicator(historicPrices);
                sma50Daily.ApplyIndicator(historicPrices);
                SimpleMovingAverageDailyVolumeDayIndicator.Month.ApplyIndicator(historicPrices);
                SimpleMovingAverageDailyVolumeDayIndicator.Quarter.ApplyIndicator(historicPrices);

                //run analysers
                allTimeHighResult = allTimeHighBreakoutPriceDatabaseAnalyser.AnalysePrices(historicPrices);

                if (allTimeHighResult.Succeeded)
                {
                    successfulResults.Add(allTimeHighResult);
                    allTimeHighResult.Symbol = fileInfo.Name.Replace(fileInfo.Extension, string.Empty);
                }

                _Log.DebugFormat("{0}% completed", Math.Round((((double)i / (double)stocksFilenamesCount) * 100), 2));
            }

            _Log.DebugFormat("Took {0}:{1}:{2} hours", stopwatch.Elapsed.Hours, stopwatch.Elapsed.Minutes, stopwatch.Elapsed.Seconds);

            _Log.Debug("Completed results, compiling output");

            var orderedResults = successfulResults.OrderBy(r => r.Symbol);

            var output = new StringBuilder();
            output.AppendLine("Name, Baselength, Basedepth, Composite, EPS, RS, SMR, AccDist, Grouprs, LastPriceDate, BaseLowDate,BaseLowPrice,PreviousHighDate, PreviousHighPrice, DaysOfPrices, PercentFromSMA50");

            foreach (var athBreakout in orderedResults)
            {
                try
                {
                    var ibdRating = Cache.IBDRatingsList.Find(r => r.Symbol == athBreakout.Symbol);

                    if (ibdRating == null)
                    {
                        _Log.WarnFormat("Couldnt find IBD rating for {0}", athBreakout.Symbol);
                    }

                    output.AppendLine(string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16}",
                                        athBreakout.Symbol,
                                        athBreakout.BaseLength,
                                        Math.Round(athBreakout.BaseDepth, 2),
                                        Math.Round(athBreakout.IntraDayBaseDepth, 2),
                                        (ibdRating == null) ? -1 : ibdRating.IBDComposite,
                                        (ibdRating == null) ? -1 : ibdRating.EPS,
                                        (ibdRating == null) ? -1 : ibdRating.RelativeStrength,
                                        (ibdRating == null) ? "-1" : ibdRating.SMR,
                                        (ibdRating == null) ? "-1" : ibdRating.AccDist,
                                        (ibdRating == null) ? "-1" : ibdRating.GroupRSRating,
                                        athBreakout.LastPriceDate.ToString("dd/MM/yyyy"),
                                        athBreakout.BaseLowDate.ToString("dd/MM/yyyy"),
                                        athBreakout.BaseLowPrice,
                                        athBreakout.PreviousHighDate.ToString("dd/MM/yyyy"),
                                        athBreakout.PreviousHighPrice,
                                        athBreakout.DaysOfPrices,
                                        Math.Round(athBreakout.PercentFromSMA50, 2)));
                }
                catch (Exception exception)
                {
                    _Log.ErrorFormat("Unexpected error adding {0} to result output --> {1}", athBreakout.Symbol, exception.ToString());
                }                
            }

            #region Email results
            _Log.Debug("Emailing results");
            try
            {
                SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
                client.EnableSsl = true;
                MailAddress from = new MailAddress("ssattin@gmail.com", "Simon Sattin");
                MailMessage message = new MailMessage(from, from);
                message.Subject = "All Time High Breakouts (Norgate data source)";
                NetworkCredential myCreds = new NetworkCredential("ssattin@gmail.com", "bergkamp_10", "");
                client.Credentials = myCreds;
                message.Body = output.ToString();
                client.Send(message);
            }
            catch (Exception exception)
            {
                _Log.Error(exception.ToString());
            }            

            #endregion

            successfulResults.OrderBy(r => r.Symbol).ToList().ForEach(r => _Log.DebugFormat(r.Symbol));

            stopwatch.Stop();
            _Log.DebugFormat("Took {0}:{1}:{2} hours to complete", stopwatch.Elapsed.Hours, stopwatch.Elapsed.Minutes, stopwatch.Elapsed.Seconds);
        }
    }
}
